home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mush-7.1.1 / folders.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  19.2 KB  |  703 lines

  1. /* @(#)folders.c    (c) copyright 10/18/86 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4.  
  5. static char oldfolder[MAXPATHLEN];
  6.  
  7. /* folder %[user]  --new mailfile is the spool/mail/login file [user].
  8.  * folder #  --new mailfile is the folder previous to the current folder
  9.  * folder &  --new mailfile is ~/mbox (or whatever "mbox" is set to)
  10.  * folder +file --new mailfile is in the directory "folder"; name is 'file'
  11.  * folder "path" --full path name or the one in current working directory.
  12.  *
  13.  * in all cases, changes are updated unless a '!' is specified after the
  14.  * folder command (e.g. "f!", "folder !" "fo!" .. all permutations)
  15.  * as usual, if new mail has arrived before the file is copied back, then
  16.  * user will be notified beforehand.
  17.  *
  18.  * RETURN -1 on error -- else return 0. All bits in msg_list are set to true.
  19.  */
  20. folder(argc, argv, list)
  21. register char **argv;
  22. char list[];
  23. {
  24.     int n, updating = !strcmp(*argv, "update"), do_read_only = 0, no_hdrs = 0;
  25.     char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
  26.     struct stat statbuf;
  27.     extern long last_spool_size;
  28.  
  29.     if (ison(glob_flags, IS_PIPE)) {
  30.     print("You can't pipe to the %s command.\n", *argv);
  31.     return -1;
  32.     } else if (ison(glob_flags, IS_SENDING)) {
  33.     print("You can't use the %s command when sending.\n", *argv);
  34.     return -1;
  35.     } else if (!tempfile || !*tempfile) {
  36.     print("You can't use the %s command in init files.\n", *argv);
  37.     return -1;
  38.     }
  39.     while (*++argv && (**argv == '-' || **argv == '!'))
  40.     if (!strcmp(*argv, "-N"))
  41.         no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES));
  42.     else if (!updating && !strcmp(*argv, "-n"))
  43.         turnoff(glob_flags, DO_UPDATE);
  44.     else if (!strcmp(*argv, "-r"))
  45.         do_read_only = 1;
  46.     else if (!strcmp(*argv, "!")) {
  47.         if (updating)
  48.         turnon(glob_flags, DO_UPDATE);    /* useful? */
  49.         else
  50.         turnoff(glob_flags, DO_UPDATE);
  51.     } else
  52.         return help(0, "folder", cmd_help);
  53.  
  54.     if (updating) {
  55.     (void) strcpy(buf, mailfile);
  56.     if (ison(glob_flags, READ_ONLY))
  57.         do_read_only = 1;
  58.     } else {
  59.     if (!*argv) {
  60.         mail_status(0);
  61.         return 0;
  62.     }
  63.     if (!strcmp(*argv, "#"))
  64.         if (!*oldfolder) {
  65.         print("No previous folder\n");
  66.         return -1;
  67.         } else
  68.         newfolder = oldfolder;
  69.     else if (!strcmp(*argv, "&")) {
  70.         if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
  71.         newfolder = DEF_MBOX;
  72.     } else
  73.         newfolder = *argv;
  74.     n = 0;
  75.     tmp = getpath(newfolder, &n);
  76.     if (n == -1) {
  77.         print("%s: %s\n", newfolder, tmp);
  78.         return -1;
  79.     } else if (n == 1) {
  80.         print("%s: is a directory\n", tmp);
  81.         return -1;
  82.     }
  83.     /* strcpy so copyback() below (which calls getpath) doesn't change
  84.      * the data that tmp intended to point to.  Get the cwd if necessary.
  85.      */
  86.     n = 0;
  87.     if (*tmp != '/') {
  88. #ifdef SYSV
  89.         extern char *getcwd();
  90.         if (!getcwd(buf, MAXPATHLEN))
  91. #else /* SYSV */
  92.         extern char *getwd();
  93.         if (!getwd(buf))
  94. #endif /* SYSV */
  95.         {
  96.         error("getcwd: %s",buf);
  97.         return -1;
  98.         }
  99.         n = strlen(buf);
  100.         buf[n++] = '/';
  101.     }
  102.     (void) strcpy(&buf[n], tmp);
  103.     }
  104. #ifdef SUNTOOL
  105.     if (istool > 1)
  106.     timeout_cursors(TRUE);
  107. #endif /* SUNTOOL */
  108.     if (stat(buf, &statbuf) == -1 || !(statbuf.st_mode & 0400)) {
  109.     error("Unable to read %s", buf);
  110. #ifdef SUNTOOL
  111.     if (istool > 1)
  112.         timeout_cursors(FALSE);
  113. #endif /* SUNTOOL */
  114.     return -1;
  115.     }
  116.     /* If the file can't be opened for writing, autoset READ_ONLY */
  117.     if (!(statbuf.st_mode & 0200))
  118.     do_read_only = 1;
  119.  
  120.     if (!(n = copyback(updating ? "Update folder?" : "Change anyway?"))) {
  121. #ifdef SUNTOOL
  122.     if (istool > 1)
  123.         timeout_cursors(FALSE);
  124. #endif /* SUNTOOL */
  125.     /* an error occured updating the folder */
  126.     return -1;
  127.     }
  128.     /* Assure that both oldfolder and mailfile are full paths */
  129.     if (strcmp(mailfile, buf) || !*oldfolder) {
  130.     n = 1; /* force load of new folder */
  131.     if (!updating)
  132.         (void) strcpy(oldfolder, *oldfolder? mailfile : buf);
  133.     strdup(mailfile, buf);
  134.     }
  135.     do_read_only? turnon(glob_flags,READ_ONLY) : turnoff(glob_flags,READ_ONLY);
  136.     last_size = spool_size = 0L;
  137.     while (msg_cnt--) {
  138.     xfree(msg[msg_cnt].m_date_recv);
  139.     xfree(msg[msg_cnt].m_date_sent);
  140.     msg[msg_cnt].m_date_recv = msg[msg_cnt].m_date_sent = NO_STRING;
  141.     }
  142.     msg_cnt = 0, msg[0].m_offset = 0L;
  143.     turnoff(glob_flags, CONT_PRNT);
  144.  
  145.     turnon(glob_flags, IGN_SIGS);
  146.     /* clear the tempfile */
  147.     if (tmpf)
  148.     (void) fclose(tmpf);
  149.     if (!do_read_only) {
  150.     if (!(tmpf = mask_fopen(tempfile, "w"))) {
  151.         error("error truncating %s", tempfile);
  152.         turnoff(glob_flags, IGN_SIGS);
  153.         return -1;
  154.     }
  155.     }
  156.     /* Don't reload the folder if it was removed */
  157.     if (n > 0) {
  158.     if (load_folder(mailfile, TRUE, NULL) < 1) {
  159.         last_msg_cnt = 0;
  160.         last_size = statbuf.st_size; /* Disable check_new_mail() */
  161.         turnoff(glob_flags, IGN_SIGS);
  162.         return -1;
  163.     }
  164.     if (do_read_only && !(tmpf = fopen(mailfile, "r"))) {
  165.         error(mailfile);
  166.         turnoff(glob_flags, IGN_SIGS);
  167.         return -1;
  168.     }
  169.     }
  170.     last_msg_cnt = msg_cnt;  /* for check_new_mail */
  171.     /* Prevent both bogus "new mail" messages and missed new mail */
  172.     last_size = msg[msg_cnt].m_offset;
  173.     if (!strcmp(mailfile, spoolfile))
  174.     spool_size = last_spool_size = last_size;
  175. #ifdef SUNTOOL
  176.     if (istool) {
  177.     extern Panel_item folder_text_item;
  178.     Rect *rect = (Rect *)window_get(hdr_sw, WIN_RECT);
  179.     (void) pw_rop(hdr_win, 0,0, rect->r_width, rect->r_height, PIX_CLR,
  180.         (struct pixrect *) 0,0,0);
  181.     panel_set_value(folder_text_item, mailfile);
  182.     }
  183. #endif /* SUNTOOL */
  184.  
  185.     if (!updating || current_msg >= msg_cnt)
  186.     current_msg = (msg_cnt? 0 : -1);
  187.     turnoff(glob_flags, IGN_SIGS);
  188.  
  189.     /* now sort messages according a user-defined default */
  190.     if (!updating && msg_cnt > 1 && !strcmp(mailfile, spoolfile) &&
  191.         (tmp = do_set(set_options, "sort"))) {
  192.     (void) sprintf(buf, "sort %s", tmp);
  193.     if ((argv = mk_argv(buf, &argc, TRUE)) && argc > 0) {
  194.         /* msg_list can't be null for do_command and since we're not
  195.          * interested in the result, call sort directly
  196.          */
  197.         (void) sort(argc, argv, NULL);
  198.         free_vec(argv);
  199.         if (!updating)
  200.         current_msg = 0;    /* Sort may move the current message */
  201.     }
  202.     }
  203.     turnoff(glob_flags, DO_UPDATE);
  204.  
  205.     /* go to first NEW message */
  206.     for (n = 0; n < msg_cnt && ison(msg[n].m_flags, OLD); n++)
  207.     ;
  208.     if (n == msg_cnt) {
  209.     turnoff(glob_flags, NEW_MAIL);
  210.     if (!updating) {
  211.         /* no new message found -- try first unread message */
  212.         for (n = 0; n < msg_cnt && isoff(msg[n].m_flags, UNREAD); n++)
  213.         ;
  214.     }
  215.     } else {
  216.     turnon(glob_flags, NEW_MAIL);
  217.     /* default for toolmode is true */
  218.     if (istool && !chk_option("quiet", "tool"))
  219.         bell();
  220.     }
  221.     if (msg_cnt && (!updating || current_msg < 0))
  222.     current_msg = (n == msg_cnt ? 0 : n);
  223.  
  224.     if ((!istool || istool && !msg_cnt) && !iscurses)
  225.     mail_status(0);
  226.     /* be quiet if we're piping */
  227.     if (!istool && !updating && !no_hdrs && msg_cnt
  228.         && isoff(glob_flags, DO_PIPE))
  229.     (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list);
  230. #ifdef SUNTOOL
  231.     if (istool > 1) {
  232.     if (!msg_cnt)
  233.         print("No Mail in %s\n", mailfile);
  234.     if (msg_cnt) {
  235.         display_msg(current_msg, (long)0);
  236.         do_hdrs(0, DUBL_NULL, NULL);
  237.     }
  238.     timeout_cursors(FALSE);
  239.     }
  240. #endif /* SUNTOOL */
  241.     if (list) {
  242.     clear_msg_list(list);
  243.     bitput(list, list, msg_cnt, =~); /* macro */
  244.     }
  245.     return 0;
  246. }
  247.  
  248. folders(argc, argv)
  249. register char **argv;
  250. {
  251.     register char *p;
  252.     char buf[128], unused[MAXMSGS_BITS];
  253.  
  254.     if (argv && argv[1] && !strcmp(argv[1], "-?"))
  255.     return help(0, "folders", cmd_help);
  256.  
  257.     if (!(p = do_set(set_options, "folder")) || !*p)
  258.     p = DEF_FOLDER;
  259.     (void) sprintf(buf, "ls -FR %s", p);
  260.     if (argv = make_command(buf, TRPL_NULL, &argc))
  261.     return do_command(argc, argv, unused);
  262.     return -1;
  263. }
  264.  
  265. /*
  266.  * Determine whether a file could be a folder.  If prompt is non-NULL,
  267.  * ask the user whether we should treat the file as a folder anyway.
  268.  */
  269. test_folder(name, prompt)
  270. char *name, *prompt;
  271. {
  272.     char line[BUFSIZ], *p;
  273.     FILE *fp = fopen(name, "r");
  274.     int retval = FALSE;
  275.  
  276.     if (!fp)
  277.     return 0;
  278.     if (fgets(line, sizeof line - 1, fp)) {
  279. #ifndef MSG_SEPARATOR
  280.     if (p = any(line, " \t")) {
  281.         skipspaces(1);
  282.         p = any(p, " \t");
  283.     }
  284.     if (p && !strncmp(line, "From ", 5) && (p = parse_date(p + 1)))
  285. #else /* MSG_SEPARATOR */
  286.     if (!strncmp(line, MSG_SEPARATOR, strlen(MSG_SEPARATOR)))
  287. #endif /* MSG_SEPARATOR */
  288.         retval = TRUE;
  289.     } else
  290.     retval = TRUE;    /* Empty files are legitimate folders */
  291.     (void) fclose(fp);
  292.     if (prompt && !retval) {
  293.     char buf[BUFSIZ];
  294. #ifdef SUNTOOL
  295.     if (istool) {
  296.         (void) sprintf(buf, "\"%s\": %s", name, prompt);
  297.         return ask(buf);
  298.     }
  299. #endif /* SUNTOOL */
  300.     print("\"%s\": %s [n] ", name, prompt);
  301.     buf[0] = 0;
  302.     retval = (Getstr(buf, sizeof (buf), 0) && lower(*buf) == 'y');
  303.     }
  304.     return retval;
  305. }
  306.  
  307. /* merge_folders filename  -- concatenate the folder specified by filename
  308.  *                            to the current folder.
  309.  *
  310.  * RETURN -1 on error -- else return 0.  A bit in msg_list is set to true
  311.  * for each of the "new" messages read in to the current folder.
  312.  */
  313. merge_folders(n, argv, list)
  314. register char **argv, list[];
  315. {
  316.     int no_hdrs = 0, newest_msg;
  317.     long orig_offset;
  318.     char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
  319.  
  320.     if (ison(glob_flags, IS_PIPE)) {
  321.     print("You can't pipe to the %s command.\n", *argv);
  322.     return -1;
  323.     } else if (ison(glob_flags, IS_SENDING)) {
  324.     print("You can't use the %s command while sending.\n", *argv);
  325.     return -1;
  326.     }
  327.  
  328.     while (*++argv && **argv == '-')
  329.     if (!strcmp(*argv, "-?"))
  330.         return help(0, "merge", cmd_help);
  331.     else if (!strcmp(*argv, "-N"))
  332.         no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES));
  333.  
  334.     if (!*argv)
  335.     return 0;
  336.  
  337.     if (ison(glob_flags, READ_ONLY)) {
  338.     print("Folder is read-only.\n");
  339.     return -1;
  340.     }
  341.  
  342.     if (!strcmp(*argv, "#"))
  343.     if (!*oldfolder) {
  344.         print("No previous folder\n");
  345.         return -1;
  346.     } else
  347.         newfolder = oldfolder;
  348.     else if (!strcmp(*argv, "&")) {
  349.     if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
  350.         newfolder = DEF_MBOX;
  351.     } else
  352.     newfolder = *argv;
  353.     n = 0;
  354.     tmp = getpath(newfolder, &n);
  355.     if (n == -1) {
  356.     print("%s: %s\n", newfolder, tmp);
  357.     return -1;
  358.     } else if (n == 1) {
  359.     print("%s: is a directory\n", tmp);
  360.     return -1;
  361.     }
  362.  
  363.     turnon(glob_flags, IGN_SIGS);
  364.     orig_offset = msg[msg_cnt].m_offset;
  365.     (void) load_folder(tmp, 2, list);
  366.     msg[msg_cnt].m_offset = orig_offset;
  367.     newest_msg = last_msg_cnt;
  368.     Debug("newest_msg = %d\n", newest_msg);
  369.     last_msg_cnt = msg_cnt;  /* for check_new_mail */
  370.     Debug("msg_cnt = %d\n", msg_cnt);
  371.     (void) mail_size();
  372.     turnoff(glob_flags, IGN_SIGS);
  373.  
  374.     if ((!istool || istool && !msg_cnt)
  375.         && !iscurses && !ison(glob_flags, PRE_CURSES))
  376.     mail_status(0);
  377.     /* be quiet if we're piping or if told not to show headers */
  378.     if ((istool || !no_hdrs) && isoff(glob_flags, DO_PIPE)
  379.         && newest_msg < msg_cnt)
  380.     (void) cmd_line(sprintf(buf, "headers %d", newest_msg + 1), NULL);
  381.     return 0;
  382. }
  383.  
  384. /*
  385.  * Default digest article separator
  386.  */
  387. #define ARTICLE_SEP "--------"
  388.  
  389. /*
  390.  * Undigestify messages.  If a message is in digest-format, there are many
  391.  * messages within this message which are to be extracted.  Kinda like a
  392.  * folder within a folder.  By default, this routine will create a new
  393.  * folder that contains the new messages.  -m option will merge the new
  394.  * messages into the current folder.
  395.  */
  396. do_undigest(n, argv, list)
  397. char *argv[], list[];
  398. {
  399.     int r, articles = 0, merge = 0, appending = 0;
  400.     char buf[MAXPATHLEN], cmdbuf[MAXPATHLEN], newlist[MAXMSGS_BITS], *dir;
  401.     char *art_sep = ARTICLE_SEP, *mktemp();
  402.     FILE *fp;
  403.  
  404.     while (argv && *++argv && **argv == '-') {
  405.     switch(argv[0][1]) {
  406.         case 'm':
  407.         if (ison(glob_flags, READ_ONLY)) {
  408.             print("Folder is read only.\n");
  409.             return -1;
  410.         }
  411.         merge++;
  412.         when 'p':
  413.         if (*++argv)
  414.             art_sep = *argv;
  415.         else {
  416.             print("Specify separator pattern with -p.\n");
  417.             return -1;
  418.         }
  419.         otherwise: return help(0, "undigest", cmd_help);
  420.     }
  421.     }
  422.  
  423.     if ((n = get_msg_list(argv, list)) == -1)
  424.     return -1;
  425.  
  426.     argv += n;
  427.  
  428.     if (*argv) {
  429.     int isdir = 1; /* Ignore file nonexistance errors */
  430.     (void) strcpy(buf, getpath(*argv, &isdir));
  431.     if (isdir < 0) {
  432.         print("%s: %s\n", *argv, buf);
  433.         return -1;
  434.     } else if (isdir == 1) {
  435.         print("%s: is a directory\n", buf);
  436.         return -1;
  437.     }
  438.     } else {
  439.     register char *p, *p2;
  440.     if (Access(dir = ".", W_OK) == 0 ||
  441.         (dir = do_set(set_options, "folder")) ||
  442.         (dir = do_set(set_options, "tmpdir")))
  443.         dir = getdir(dir); /* expand metachars */
  444.     if (!dir)
  445. alted:
  446.         dir = ALTERNATE_HOME;
  447.     for (n = 0; n < msg_cnt; n++)
  448.         if (msg_bit(list, n))
  449.         break;
  450.  
  451.     if (!(p = header_field(n, "subject")))
  452.         (void) mktemp(sprintf(buf, "%s/digestXXXXX", dir));
  453.     else {
  454.         if (!lcase_strncmp(p, "re: ", 4))
  455.         p += 4;
  456.         for (p2 = p; *p2; p2++)
  457.         if (!isalnum(*p2) && *p2 != '-' && *p2 != '.') {
  458.             *p2 = 0;
  459.             break;
  460.         }
  461.         p2 = buf + Strcpy(buf, dir);
  462.         *p2++ = '/';
  463.         (void) strcpy(p2, p);
  464.     }
  465.     }
  466.  
  467.     if (!Access(buf, W_OK))
  468.     appending = ((fp = mask_fopen(buf, "a")) != NULL_FILE);
  469.     else
  470.     fp = mask_fopen(buf, "w");
  471.     if (!fp) {
  472.     if (!*argv && strcmp(dir, ALTERNATE_HOME))
  473.         goto alted;
  474.     error("can't create %s", buf);
  475.     return -1;
  476.     }
  477.  
  478.     for (n = 0; n < msg_cnt; n++) {
  479.     if (!msg_bit(list, n))
  480.         continue;
  481.  
  482.     print("undigesting message %d\n", n+1);
  483.     /* copy message into file making sure all headers exist. */
  484.     r = undigest(n, fp, art_sep);
  485.     if (r <= 0)
  486.         break;
  487.     articles += r;
  488.     }
  489.     (void) fclose(fp);
  490.     if (r <= 0) {
  491.     if (!appending)
  492.         (void) unlink(buf);
  493.     return -1;
  494.     }
  495.     if (merge) {
  496.     (void) cmd_line(sprintf(cmdbuf, "\\merge -N %s", buf), newlist);
  497.     (void) unlink(buf);
  498.     print("Merged in %d messages.\n", articles);
  499.     } else
  500.     print("Added %d messages to \"%s\".\n", articles, buf);
  501.     clear_msg_list(list);
  502.     for (n = 0; n < msg_cnt; n++)
  503.     if (msg_bit(newlist, n))
  504.         set_msg_bit(list, n);
  505.     return 0;
  506. }
  507.  
  508. /*
  509.  * split digest-message 'n' to file "fp" using article separator "sep".
  510.  * return number of articles copied or -1 if system error on fputs.
  511.  * A digest is a folder-in-a-message in a special, semi-standard form.
  512.  */
  513. undigest(n, fp, sep)
  514. int n;
  515. FILE *fp;
  516. char *sep;
  517. {
  518.     int  art_cnt = 0, on_hdr = -1; /* on_hdr is -1 if hdr not yet found */
  519.     int  sep_len = (sep ? strlen(sep) : strlen(sep = ARTICLE_SEP));
  520.     long get_hdr = 0L;
  521.     char from[HDRSIZ], line[HDRSIZ], last_sep[HDRSIZ];
  522.     char from_hdr[256], afrom[256], adate[64];
  523.     char *fdate = "Xxx Xxx 00 00:00:00 0000"; /* Dummy date in ctime form */
  524.     SIGRET (*oldint)(), (*oldquit)();
  525.  
  526.     if (!msg_get(n, from, sizeof from)) {
  527.     error("Unable to find msg %d", n+1);
  528.     return -1;
  529.     }
  530. #ifndef MSG_SEPARATOR
  531.     else {
  532.     char *p = from + 5;
  533.     skipspaces(0);
  534.     p = index(p, ' ');
  535.     if (p) {
  536.         skipspaces(0);
  537.         fdate = p;
  538.     }
  539.     if (fputs(from, fp) == EOF)
  540.         return -1;
  541.     }
  542. #endif /* !MSG_SEPARATOR */
  543.  
  544.     on_intr();
  545.     *afrom = *adate = *last_sep = '\0';
  546.     while (ftell(tmpf) < msg[n].m_offset + msg[n].m_size &&
  547.        fgets(line, sizeof (line), tmpf)) {
  548.     if (ison(glob_flags, WAS_INTR))
  549.         goto handle_error;
  550.     if (*line == '\n' && on_hdr > 0)    /* blank line -- end of header */
  551.         on_hdr = 0;
  552.  
  553.     /* Check for the beginning of a digest article */
  554.     if (!strncmp(line, sep, sep_len)) {
  555.         if (get_hdr) {
  556.         if (do_set(set_options, "warning"))
  557.             print("Article with no header? (added to article #%d)\n",
  558.                 art_cnt);
  559.         /* Don't start a new message for whatever this is,
  560.          * just fseek back and keep appending to the last one.
  561.          */
  562.         if (fseek(tmpf, get_hdr, L_SET) < 0 ||
  563.             fputs(last_sep, fp) == EOF) {
  564.             art_cnt = -1;
  565.             goto handle_error;
  566.         }
  567.         get_hdr = 0L;
  568.         on_hdr = 0;
  569.         } else {
  570.         (void) strcpy(last_sep, line);
  571.         get_hdr = ftell(tmpf);
  572.         *afrom = *adate = '\0';
  573.         on_hdr = -1;    /* Haven't found the new header yet */
  574.         }
  575.         continue;
  576.     }
  577.  
  578.     if (get_hdr) {
  579.         char *p = *line == '>' ? line + 1 : line;
  580.         if (*line == '\n') {
  581.         if (*afrom || *adate) {
  582.             (void) fseek(tmpf, get_hdr, L_SET);
  583.             /* Terminate the previous article */
  584.             art_cnt++;
  585. #ifdef MSG_SEPARATOR
  586. #ifdef END_MSG_SEP
  587.             if (fputs(END_MSG_SEP, fp) == EOF) {
  588.             art_cnt = -1;
  589.             goto handle_error;
  590.             }
  591. #endif /* END_MSG_SEP */
  592. #ifdef MMDF
  593.             /* MMDF has a newline in MSG_SEPARATOR */
  594.             if (fputs(MSG_SEPARATOR, fp) == EOF)
  595. #else /* !MMDF */
  596.             /* Other MSG_SEPARATORs need a newline */
  597.             if (fputs(MSG_SEPARATOR, fp) == EOF ||
  598.                 fputc('\n', fp) == EOF)
  599. #endif /* MMDF */
  600. #else /* !MSG_SEPARATOR */
  601.             /* Everybody else needs a From_ line */
  602.             if (fprintf(fp, "From %s  %s", *afrom ? afrom : "unknown",
  603.                 *adate ? date_to_ctime(adate) : fdate) == EOF)
  604. #endif /* MSG_SEPARATOR */
  605.             {
  606.             art_cnt = -1;
  607.             goto handle_error;
  608.             }
  609.             /* Make sure there is a From: without a leading > */
  610.             if (*afrom && *from_hdr && fputs(from_hdr, fp) == EOF) {
  611.             art_cnt = -1;
  612.             goto handle_error;
  613.             }
  614.             get_hdr = 0L;
  615.         } else if (on_hdr < 0)
  616.             /* Skip blanks between "--------" and the hdr */
  617.             get_hdr = ftell(tmpf);
  618.         } else if (on_hdr < 0)
  619.         on_hdr = 1;
  620.         if (on_hdr > 0 && !strncmp(p, "From: ", 6)) {
  621.         (void) get_name_n_addr(p + 6, NULL, afrom);
  622.         (void) no_newln(afrom);
  623.         /* Get the From: minus the leading > */
  624.         if (p != line)
  625.             (void) strcpy(from_hdr, p);
  626.         else /* We don't need From: twice! */
  627.             *from_hdr = '\0';
  628.         } else if (on_hdr > 0 && !strncmp(line, "Date: ", 6)) {
  629.         if (p = parse_date(line+6))
  630.             (void) strcpy(adate, p);
  631.         } else if (on_hdr > 0 && !lcase_strncmp(line, "end", 3)) {
  632.         if (!*afrom && !*adate)
  633.             break;
  634.         }
  635.     } else if (fputs(line, fp) == EOF) {
  636.         /* Pipe broken, out of file space, etc */
  637.         art_cnt = -1;
  638.         goto handle_error;
  639.     }
  640.     }
  641.     ++art_cnt;
  642. #ifdef END_MSG_SEP
  643.     if (art_cnt > 0 && fputs(END_MSG_SEP, fp) == EOF) {
  644.     art_cnt = -1;
  645.     goto handle_error;
  646.     }
  647. #endif /* END_MSG_SEP */
  648.     /* If we're still looking for a header, there is some stuff left
  649.      * at the end of the digest.  Create an extra article for it.
  650.      */
  651.     if (get_hdr) {
  652.     char *p;
  653.     (void) fseek(tmpf, get_hdr, L_SET);
  654.     if (ftell(tmpf) >= msg[n].m_offset + msg[n].m_size)
  655.         goto handle_error;
  656. #ifdef MSG_SEPARATOR
  657. #ifdef MMDF
  658.     if (fputs(MSG_SEPARATOR, fp) == EOF)
  659. #else /* !MMDF */
  660.     if (fputs(MSG_SEPARATOR, fp) == EOF ||
  661.         fputc('\n', fp) == EOF)
  662. #endif /* MMDF */
  663. #else /* !MSG_SEPARATOR */
  664.     if (fputs(from, fp) == EOF)
  665. #endif /* MSG_SEPARATOR */
  666.         art_cnt = -1;
  667.     if (!(p = header_field(n, "from")))
  668.         p = "Mush-Undigest (Real author unknown)";
  669.     if (fprintf(fp, "From: %s\n", p) == EOF)
  670.         art_cnt = -1;
  671.     if (!(p = header_field(n, "date")))
  672.         p = fdate, (void) no_newln(p);
  673.     if (fprintf(fp, "Date: %s\n", p) == EOF)
  674.         art_cnt = -1;
  675.     if (!(p = header_field(n, "subject")))
  676.         p = "Digest";
  677.     if (fprintf(fp, "Subject: Trailing part of %s\n\n", p) == EOF)
  678.         art_cnt = -1;
  679.     /* header_field() moves the pointer, so seek again */
  680.     (void) fseek(tmpf, get_hdr, L_SET);
  681.     while (art_cnt > 0 && ftell(tmpf) < msg[n].m_offset + msg[n].m_size
  682.         && fgets(line, sizeof (line), tmpf)) {
  683.         if (fputs(line, fp) == EOF)
  684.         art_cnt = -1;
  685. #ifdef END_MSG_SEP
  686.         if (!strncmp(line, END_MSG_SEP, strlen(END_MSG_SEP)))
  687.         break;
  688. #endif /* END_MSG_SEP */
  689.     }
  690.     /* The END_MSG_SEP, if any, of the digest will have been output
  691.      * by the while loop above, so we don't need to add one here.
  692.      */
  693.     ++art_cnt;
  694.     }
  695. handle_error:
  696.     if (art_cnt == -1)
  697.     error("cannot completely undigest");
  698.     else if (ison(glob_flags, WAS_INTR))
  699.     art_cnt = -1;
  700.     off_intr();
  701.     return art_cnt;
  702. }
  703.